extends KinematicBody2D
export(PackedScene) var hit_scene

# Declare member variables here. Examples:
# var a = 2
# var b = "text"

onready var anim_sprite = $Sprite
onready var anim_tree_main = $AnimationTreeMain
onready var anim_player_main = $AnimationTreeMain/AnimationPlayerMain

onready var anim_playback_root = anim_tree_main["parameters/playback"]
onready var anim_playback_main = anim_tree_main["parameters/mainAnimStateMachine/playback"]

var anim_attack_frame_max = 2
var anim_attack_frame = 0

const GRAVITY = 600
const FRICTION_FLOOR = 0.25
const FRICTION_AIR = 0.02
const JUMP_BUFFER_TIME = 0.1


var motion = Vector2.ZERO

var fall_speed_max = 480
var jump_speed_max = 320
var jump_force = 280
var move_speed = 120
var jump_buffer = 0

var attack_damage = 20
var attack_timer_max = 0.18
var attack_timer = 0
var attack_delay = 0
var attack_buffer = 0
var is_just_attack = false

var hp = 100
var hp_max = 100
var is_defeat = false
var is_jumping_ready = false
var x_flip = 1

var hp_bar

func set_hp_bar(node):
	hp_bar = node
	hp_bar.min_value = 0
	hp_bar.max_value = hp_max
	hp_bar.value = hp

# Called when the node enters the scene tree for the first time.
func _ready():
	set_hp_bar(get_parent().get_node("totalUI/HeroHPBar"))
	
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass
	
func _physics_process(delta):
	# Init
	is_just_attack = false
	
	# Timer
	if attack_timer > 0:
		attack_timer -= delta
	if attack_buffer > 0:
		attack_buffer -= delta
	if attack_delay > 0:
		attack_delay -= delta
	if jump_buffer > 0:
		jump_buffer -= delta
	
	
	# Move and Action
	
	var x_input = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	var y_input = Input.get_action_strength("ui_down")
	var jump_input = Input.get_action_strength("ui_jump")
	var attack_input = Input.is_action_just_released("ui_attack")
		
	if attack_input or attack_buffer > 0:
		if attack_timer <= 0:
			print("attack")
			is_just_attack = true
#			motion.y = min(motion.y, -30)
			attack_timer = attack_timer_max
	
	if attack_input:
		if attack_timer > 0:
			attack_buffer = min(0.12,attack_timer_max)
			
	if x_input != 0:
		if x_flip != x_input:
			motion.x = x_flip * 0.05
			x_flip = x_input
			anim_sprite.get_node("AttackArea/AttackBox").position.x *= -1
		motion.x += x_input * move_speed * 4 * delta
	
	motion.y += GRAVITY * delta
	
	if is_on_floor():
		is_jumping_ready = true
		
	if is_jumping_ready:
		jump_buffer = JUMP_BUFFER_TIME
		if x_input == 0:
			motion.x = lerp(motion.x, 0, FRICTION_FLOOR)
		if jump_input == 1:
			is_jumping_ready = false
			motion.y = -jump_force
	else:
		if jump_buffer > 0 and jump_input:
			is_jumping_ready = false
			jump_buffer = 0
			motion.y = -jump_force
			
		if x_input == 0:
			motion.x = lerp(motion.x, 0, FRICTION_AIR)
		
		if Input.is_action_just_released("ui_jump") and motion.y < -jump_force / 2:
			motion.y = -jump_force / 3
	
	motion.x = clamp(motion.x, -move_speed, move_speed)
	if attack_delay > 0 and is_on_floor():
		motion.x = clamp(motion.x, -move_speed / 2, move_speed / 2)
	motion.y = clamp(motion.y, -jump_speed_max, fall_speed_max)
	
	motion = move_and_slide(motion, Vector2.UP)
	
	
	# Animation
	if x_flip == 1:
		anim_sprite.flip_h = false
	elif x_flip == -1:
		anim_sprite.flip_h = true
	
	
#	if attack_input:
	if is_just_attack:
		attack_delay = min(0.2, attack_timer_max)
		print("attack switch" + String(anim_attack_frame))
		anim_playback_root.travel("attack" + String(anim_attack_frame))
		anim_attack_frame = (anim_attack_frame + 1) % anim_attack_frame_max
	elif attack_delay <= 0:
		anim_playback_root.travel("mainAnimStateMachine")
		
		if is_on_floor():
			if x_input != 0:
#				print("walk")
#				print(x_input)
				anim_playback_main.travel("walk")
			else:
#				print("idle")
#				print(x_input)
				anim_playback_main.travel("idle")
		else:
			if motion.y < 0:
				anim_playback_main.travel("jump")
			else:
				anim_playback_main.travel("fall")
			
func defeat():
	is_defeat = true
	get_parent().get_node("totalUI/Win").visible = true
	get_parent().get_node("totalUI/Reset").visible = true
		
func take_damage(damage):
	hp -= damage
	hp_bar.value = hp
	if hp <= 0:
		defeat()

func _on_Area2D_area_entered(area):
	print("get")
	is_jumping_ready = true
	if is_on_floor() == false:
		motion.y = -jump_force * (attack_timer_max)
		motion.x = motion.x / 3
	if area.is_in_group("Enemy"):
		var hitbox = area.get_node("HitBox") as CollisionShape2D
		var hit = hit_scene.instance()
		var offsetx = int((hitbox.shape as RectangleShape2D).extents.x * 3)
		var offsety = int((hitbox.shape as RectangleShape2D).extents.y * 3)
		
		hit.position.x = hitbox.position.x
		hit.position.y = hitbox.position.y
		
		hit.position.x += offsetx / 2 - randi() % offsetx
		hit.position.y += offsety / 2 - randi() % offsety
		
		area.add_child(hit)
		
		area.get_parent().take_damage(attack_damage)
